﻿#include <VisitorNodeToItem.h>
#include <SceneViewer.h>
#include <NodeInformationContainer.h>
#include <SceneViewerFunctions.h>
//#include <ObjectListGenerate.h>
#include <OsgClassDataSource/ObjectOsg.h>
#include <NodeInfoContainer.h>
#include <ClassFactoryObjectOsg.h>
#include <ClassFactoryObjectOsg.h>
#include <osg/ValueObject>
std::string getUiTypeString2(const std::string& _type_string)//命名为2就是为了避免编译错误，重定义，这里偷懒了
{
    std::string _ui_type_string;
    int pos1 = _type_string.find(":");
    if (pos1 != std::string::npos)
    {
        _ui_type_string = _type_string.substr(pos1+2, _type_string.size()-1);
    }
    else
    {
        pos1 = _type_string.find(" ");
        _ui_type_string = _type_string.substr(pos1+1, _type_string.size()-1);
    }
    return _ui_type_string;
}
VisitorNodeToItem::VisitorNodeToItem()
{
	setTraversalMode(osg::NodeVisitor::TraversalMode::TRAVERSE_ALL_CHILDREN);
    setTraversalMask(0x1);
    //setNodeMaskOverride(0xffffffff);//这里设置两下，可以保证本visitor可以遍历到所有的node，就算node本身的mask设置成了0，也可以遍历到，这是参考osg文档中的nodevisitor有关mask的部分。
    m_currentItem = NULL;
    m_rootItem = NULL;
    m_previousItemList.push_back(NULL);
    m_geodeCount = 0;
}

VisitorNodeToItem::~VisitorNodeToItem()
{

}

void VisitorNodeToItem::apply( osg::Node& node )
{
    NodeInfoContainer* infoContainer = dynamic_cast<NodeInfoContainer*>((&node)->getUserDataContainer());
    if(infoContainer == NULL)
    {
        ObjectOsg* objOsgPtr = creatObjOsg(&node);

        if(objOsgPtr != NULL)
        {
            if(m_previousItemList.at(m_previousItemList.size()-1) != NULL)
                m_previousItemList.at(m_previousItemList.size()-1)->appendRow(objOsgPtr->getObjItem());

            m_currentItem = objOsgPtr->getObjItem();
        }
    }
    else
    {
        m_currentItem = infoContainer->getObjectInspectorItem();
    }

    //if node is a geode
    osg::Geode* geode = dynamic_cast<osg::Geode*>(&node);
    if(geode != NULL)
    {
        geode->setUserValue("geodeIndex", m_geodeCount);
        m_geodeCount++;

    }

    m_previousItemList.push_back(m_currentItem);
    if(node.getName() == "SceneViewerRootNode")
    {
        handleCameraManipulator();
        SceneViewer::instance()->getModelRoot()->accept(*this);
    }
    else
    {
        traverse(node);
    }

    m_previousItemList.pop_back();

    //m_currentItem = previousItem;
}

//void VisitorNodeToItem::apply(osg::Geode &node)
//{

//}

void VisitorNodeToItem::apply( osgViewer::Viewer& viewer )
{
    /*
    NodeInfoContainer* infoContainer = dynamic_cast<NodeInfoContainer*>(SceneViewer::instance()->getUserDataContainer());
    if(infoContainer == NULL)
    {
        ObjectOsg* objOsgPtr = creatObjOsg(SceneViewer::instance());

        if(objOsgPtr != NULL)
        {
            if(m_previousItemList.at(m_previousItemList.size()-1) != NULL)
                m_previousItemList.at(m_previousItemList.size()-1)->appendRow(objOsgPtr->getObjItem());

            m_currentItem = objOsgPtr->getObjItem();

        }
    }
    else
    {
        m_currentItem = infoContainer->getObjectInspectorItem();

    }
    m_previousItemList.push_back(m_currentItem);
    SceneViewer::instance()->getModelRoot()->accept(*this);
    */
}
void VisitorNodeToItem::setRootItem(QStandardItem* root_item)
{
    m_previousItemList.clear();
    m_rootItem = root_item;
    m_currentItem = m_rootItem;
    m_previousItemList.push_back(m_currentItem);
}

ObjectOsg *VisitorNodeToItem::creatObjOsg(osg::Object *node_ptr)
{
    //std::cout<<"VisitorNodeToItem::creatObjOsg info = "<<(int)node_ptr<<std::endl;

    ObjectOsg* osgOsgPtr = NULL;
    std::string obj_type_name = typeid(*node_ptr).name();
    std::string type_name = getUiTypeString2(obj_type_name);

    if(node_ptr->getName() == "SceneViewModelRoot") type_name = "ModelRoot";
    if(node_ptr->getName() == "SceneViewerRootNode") type_name = "SceneViewer";

    ClassFactoryObjectOsg factory;
    EObject* eObjPtr = factory.creatObject(QString::fromStdString(type_name) + QString("Osg"));
    osgOsgPtr = dynamic_cast<ObjectOsg*>(eObjPtr);
    if(osgOsgPtr != NULL)
    {
        osg::ref_ptr<osg::Object> objRef(node_ptr);
        osgOsgPtr->replaceOsgObject(objRef);
        osgOsgPtr->refreshItemTest();
        osgOsgPtr->refreshInfoContainer();
//        NodeInfoContainer* newInfoContainer = new NodeInfoContainer;
//        newInfoContainer->setObjectInspectorItem( osgOsgPtr->getObjItem() );
//        node_ptr->setUserDataContainer(newInfoContainer);

    }
    else
    {
        //osgOsgPtr = new NodeOsg();
    }

    return osgOsgPtr;
}

void VisitorNodeToItem::setIfGenerateAppliedNodeItem(bool bool_value)
{
    m_ifGenerateAppliedNodeItem = bool_value;
}

int VisitorNodeToItem::getGeodeCount()
{
    return m_geodeCount;
}

void VisitorNodeToItem::clearGeodeCount()
{
    m_geodeCount = 0;
}

void VisitorNodeToItem::handleCameraManipulator()
{
    int camera_mani_size = SceneViewerFunctions::getCameraVectorSize();
    for (int i = 0 ;i < camera_mani_size;i++)
    {
        osg::ref_ptr<osgGA::CameraManipulator> cam_mani_ptr = SceneViewerFunctions::sceneViewerGetCameraManipulator(i);
        NodeInfoContainer* infoContainer = dynamic_cast<NodeInfoContainer*>(cam_mani_ptr->getUserDataContainer());
        if(infoContainer == NULL)
        {
            ObjectOsg* objOsgPtr = creatObjOsg(cam_mani_ptr);

            if(objOsgPtr != NULL)
            {
                if(m_previousItemList.at(m_previousItemList.size()-1) != NULL)
                {
                    //if modelRoot has item
                    NodeInfoContainer* modelRootInfoContainer = dynamic_cast<NodeInfoContainer*>(SceneViewer::instance()->getModelRoot()->getUserDataContainer());
                    if(modelRootInfoContainer != NULL)
                    {
                        int modelRootRowIndex = modelRootInfoContainer->getObjectInspectorItem()->row();
                        m_previousItemList.at(m_previousItemList.size()-1)->insertRow(modelRootRowIndex, objOsgPtr->getObjItem());
                    }
                    else
                    {
                        m_previousItemList.at(m_previousItemList.size()-1)->appendRow(objOsgPtr->getObjItem());

                    }

                }

            }
        }
        else
        {
           // m_previousItemList.at(m_previousItemList.size()-1)->appendRow(infoContainer->getObjectInspectorItem(););

        }

    }
}
